﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.ObjectModel;
using System.Reflection;
using System.IO;
using System.ComponentModel;
using System.Text.RegularExpressions;
using IWshRuntimeLibrary;
using FinPlusAssembler;
using FinPlusInterfaces;

namespace FinPlusCompView
{
    public partial class FinPlusMontage : FinPlusControl
    {
        [State(Test = true)]
        public override bool IsValid { get; set; }
        [State(Test = true)]
        public int ColumnsCount { get { return dataGrid.Columns.Count; } }
        [State(Test = true)]
        public int ItemsCount { get { return dataGrid.Items.Count; } }
        [State(Save = true)]
        public new double Height { get { return base.Height; } set { base.Height = value; } }
        [State(Save = true)]
        public new double Width { get { return base.Width; } set { base.Width = value; } }

        private readonly Views _views = new Views();
        private readonly ITransport _tran;

        //construct
        public FinPlusMontage(string clientExecutable)
        {
            InitializeComponent();
            Env _env;
            var config = Assembly.GetEntryAssembly().ConfigPath().ConfigXml(out _env);
            Env = _env;
            _tran = IOC.New<ITransport>(config["localmessagingsettings"]["address"], int.Parse(config["localmessagingsettings"]["port"]));
            _tran.Listener.MessageRecieved += Message_Event;
            _views.LoadViews(Paths.Values["FolderViews"], Assembly.GetExecutingAssembly().Path() + clientExecutable, Env, _tran);
            
            dataGrid.ItemsSource = _views;
            IsValid = true;
        }

        //common control interface
        public override void CmdExecute(IPod command)
        {
            try
            {
                CmdCapture(command);

                switch ((Cmds)Enum.Parse(typeof(Cmds), command.Name, true))
                {
                    case Cmds.Open: OpenView(); break;
                    case Cmds.Home: ((View)dataGrid.SelectedItem).Home(); break;
                    case Cmds.Save: ((View)dataGrid.SelectedItem).Save(); break;
                    case Cmds.Minimize: ((View)dataGrid.SelectedItem).Minimize(); break;
                    case Cmds.Maximize: ((View)dataGrid.SelectedItem).Maximize(); break;
                    case Cmds.CreateShortcut: ((View)dataGrid.SelectedItem).CreateShortcut(); break;
                    case Cmds.Close: CloseView(); break;
                    case Cmds.OnClose: OnCloseView(command["Tag"].ToString()); break;
                    default: throw new Exception(string.Format("cmd not recognised {0}", command.Name));
                }
            }
            catch (CmdExecuteException e)
            {
                IsValid = Level.Warning.Log(Id, Config, e.Message, e);
            }
        }

        public override void Dispose()
        {
            _views.Close();
            if (_tran != null)
                _tran.Dispose();
        }

        private void OpenView()
        {
            var client = (View)dataGrid.SelectedItem;

            if (client.IsOpen)
                client.Close();
            else
                client.Open();
        }

        private void CloseView()
        {
            var client = (View)dataGrid.SelectedItem;

            if (client.IsOpen)
               client.Close();
        }

        private void OnCloseView(string linkedId)
        {
            foreach (var client in _views)
                client.OnClose(linkedId);
        }

        //cmds
        private enum Cmds { Open, Home, Save, CreateShortcut, Minimize, Maximize, Close, OnClose }

        //events
        private void Message_Event(object s, EventArgs a)
        { 
            var msg = ((MessageEventArgs)a).Message;
            if (!msg.Value.ToString().Equals(Cmds.OnClose.ToString()))
                return;
       
            if (!CheckAccess())
                Dispatcher.Invoke(() => CmdRouter(msg.Value.ToString(), msg.Topic));
            else
                CmdRouter(msg.Value.ToString(), msg.Topic);
        }
    }

    internal class Views : ObservableCollection<View>
    {
        public void LoadViews(string templatePath, string view, Env env, ITransport tran)
        {
            var dir = new DirectoryInfo(templatePath);
            foreach (var clientIOFile in dir.GetFiles("*.view"))
                this.Add(new View(clientIOFile, view, env, tran));
        }

        public void Close()
        {
            try
            {
                foreach (var client in this)
                    client.Close();
            }
            catch (Exception e)
            {
                Level.Warning.Log(e.Message, e);
            }
        }
    }

    internal class View : INotifyPropertyChanged
    {
        public string Name { get; private set; }
        public string Caption { get; private set; }
        public string LinkedId { get; private set; }
        public bool IsOpen { get { return _isOpen; } set { _isOpen = value; NotifyPropertyChanged("IsOpen"); } }
        public event PropertyChangedEventHandler PropertyChanged;

        private ITransport _tran;
        private FileInfo _fileInfo;
        private Env _env;
        private string _templatePath, _view;
        private bool _isOpen;

        //public
        public View(FileInfo fileInfo, string view, Env env, ITransport tran)
        {
            _fileInfo = fileInfo;
            _view = view;
            _env = env;
            _tran = tran;
            _templatePath = fileInfo.FullName.Replace("." + FileType.view.ToString(), string.Empty);
            _tran.Listen(LinkedId = Guids.New());
            Name = fileInfo.Name.Split('.')[0];
            Caption = Name.SplitCamelCase(); 
        }
       
        public void Open()
        {
            try
            {
                IOC.Singleton<IWindowHelper>().OpenProcess(_templatePath, Name, _env, ShowType.Show, LinkedId, "", true);
                IsOpen = true;
            }
            catch (Exception e)
            {
                Level.Warning.Log(e.Message, e);
            }
        }

        public void Close()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(IOC.New<IMessage>(Cmds.Close.ToString(), LinkedId));
            IsOpen = false;
        }

        public void OnClose(string linkedId)
        {
            if (!LinkedId.Equals(linkedId))
                return;
            IsOpen = false;
        }

        public void Home()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(IOC.New<IMessage>(Cmds.Home.ToString(), LinkedId));
        }

        public void Save()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(IOC.New<IMessage>(Cmds.Save.ToString(), LinkedId)); 
        }

        public void Minimize()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(IOC.New<IMessage>(Cmds.Minimize.ToString(), LinkedId));
        }

        public void Maximize()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(IOC.New<IMessage>(Cmds.Maximize.ToString(), LinkedId));
        }

        public void CreateShortcut()
        {
            try
            {
                var root = Paths.Values["FolderRoot"];
                var template = Paths.Values["FolderViews"] + Name;
                var path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + Caption + ".lnk";
                
                if(System.IO.File.Exists(path))
                {
                    System.IO.File.Delete(path);
                }
                else
                {
                    var shortcut = (IWshShortcut)new WshShell().CreateShortcut(path);
                    shortcut.Arguments = string.Format("{0} {1} {2} Show '{3}' '' True True False", template,  Name, _env.ToString(), Guids.New());
                    shortcut.TargetPath = root + "FinPlusClientShell.exe";
                    shortcut.WindowStyle = 1;
                    shortcut.Description = "Fin-Plus " + Name;
                    shortcut.WorkingDirectory = root;
                    shortcut.IconLocation =  root + "icon6.ico";
                    shortcut.Save();
                }
            }
            catch (Exception e)
            {
                Level.Warning.Log("Create shortcut failed", e);
            }
                  
        }

        //private
        private void NotifyPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        private enum Cmds { Close, Home, Save, Minimize, Maximize }
    }
}
